package ex3.matchmaker;

import ex3.Constants.*;
import java.util.List;
import java.util.LinkedList;

/**
 * Represents the remote Executor object.
 * @author rmn
 */
public class ExecutorData implements Comparable<ExecutorData> {
	String bindName;
	State state;
	List<Character> capabilities;
	
	/**
	 * Constructs a new ExecutorData object. The executor is created with an empty
	 * capability list, and a BUSY state.
	 * @param bindName name in the repository.
	 */
	public ExecutorData (String bindName) {
		this.bindName = bindName;
		this.state = State.BUSY;
		this.capabilities = new LinkedList<Character>();
	}
	
	/**
	 * Updates the state & capabilities of the Executor.
	 * @param state new state.
	 * @param capabilities new list of capabilities.
	 */
	public synchronized void update (State state, List<Character> capabilities) {
		this.state = state;
		this.capabilities = capabilities;
	}
	
	/**
	 * Tries to occupy the executor with the type of capability supplied.
	 * In case of success, the Executor's state is set to BUSY.
	 * @param capability the needed type of operation.
	 * @return true if the Executor was IDLE and is now taken by the caller,
	 *  false if it was already taken or if the capability isnt supported by it.
	 */
	public synchronized boolean testAndSet (Character capability) {
		if (state == State.BUSY || !capabilities.contains(capability))
			return false;
		state = State.BUSY;
		return true;		
	}
	
	/**
	 * Getter of bindName;
	 * @return bindName.
	 */
	public String getName () {
		return bindName;
	}

	/**
	 * Implementation of the Comparable interface.
	 * An executor is defined as being BEFORE another one if it has <b>less</b> capabilities.
	 * @return 0 if the executors are the same one,
	 * -1 if the current executor comes BEFORE the other one,
	 * 1 otherwise.
	 */
	public int compareTo (ExecutorData exc) { 
		if (exc == this)
			return 0;
		
		int mysize, othersize;
		synchronized(this) {
			mysize = capabilities.size();
		}
		synchronized (exc) {
			othersize = exc.capabilities.size();
		}
	    
	    if (mysize == othersize)
	    	return bindName.compareTo(exc.bindName);
	    
	    return mysize < othersize ? -1 : 1;
	}
	
}
